﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using MimiDouban.Abstract;
using System.Threading;
using System.Windows.Threading;
using MimiDouban.Extention;
using System.Diagnostics;

namespace MimiDouban.Player
{
    public class NewAudioPlayer : IPlayer
    {
        /// <summary>
        /// Windows MedeaPlayer
        /// </summary>
        private WMPLib.WindowsMediaPlayerClass mplayer;
        /// <summary>
        /// 定时器
        /// </summary>
        private Timer timer;
        private Timer bufferTimer;//缓冲计时
        /// <summary>
        /// 定时器回调处理器
        /// </summary>
        private TimerCallback timerHandler;
        /// <summary>
        /// 派发器
        /// </summary>
        private Dispatcher dispatcher;
        /// <summary>
        /// 当前是否暂停
        /// </summary>
        private bool boolIsPaused;

        public NewAudioPlayer()
        {
            mplayer = new WMPLib.WindowsMediaPlayerClass();
            timerHandler = new TimerCallback(timerHandlerMethod);
            dispatcher = Dispatcher.CurrentDispatcher;
            mplayer.enableErrorDialogs = true;

            //绑定事件处理方法
            mplayer.Buffering += new WMPLib._WMPOCXEvents_BufferingEventHandler(mplayer_Buffering);
            //mplayer.Buffering += new EventHandler(mplayer_BufferingEnded);
            //mplayer.MediaError += new EventHandler<ExceptionEventArgs>(mplayer_MediaFailed);
            //mplayer.EndOfStream +=new WMPLib._WMPOCXEvents_EndOfStreamEventHandler(mplayer_EndOfStream);
            mplayer.EndOfStream += new WMPLib._WMPOCXEvents_EndOfStreamEventHandler(mplayer_EndOfStream);
            mplayer.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(mplayer_PlayStateChange);
            mplayer.MediaError += new WMPLib._WMPOCXEvents_MediaErrorEventHandler(mplayer_MediaError);
            mplayer.Disconnect += new WMPLib._WMPOCXEvents_DisconnectEventHandler(mplayer_Disconnect);
        }

        void mplayer_Disconnect(int Result)
        {
            MimiDouban.Test.TestLog.getInstance().info("mplayer_Disconnect  " );
            throw new NotImplementedException();
        }


        #region IPlayer 成员

        bool IPlayer.isPaused()
        {
            return boolIsPaused;
        }

        void IPlayer.play(string url)
        {
            //throw new NotImplementedException();
            try
            {
                if (mplayer.currentItem != null)
                {
                    MimiDouban.Test.TestLog.getInstance().info("IPlayer.play:" + mplayer.currentItem.name);
                } 
                else
                {
                    MimiDouban.Test.TestLog.getInstance().info("IPlayer.play: currentItem null");
                }
                if (timer != null)
                {
                    timer.Dispose();
                }
                timer = new Timer(new TimerCallback(timerHandlerMethod));
                timer.Change(10, 100);
                boolIsPaused = false;
                mplayer.close();
                mplayer.stop();
                //if (mplayer.currentPlaylist.count > 10)
                //{
                //    MimiDouban.Test.TestLog.getInstance().info("playlist Count:"+mplayer.currentPlaylist.count);
                //    mplayer.currentPlaylist.clear();
                //}
                mplayer.URL = url;
                mplayer.uiMode = "None";
                mplayer.settings.playCount = 1;
                mplayer.play();
            }
            catch (System.Exception ex)
            {
                MimiDouban.Test.TestLog.getInstance().error("play catch:", ex);

            }
        }

        void IPlayer.pause()
        {
            boolIsPaused = true;
            mplayer.pause();
            //throw new NotImplementedException();
        }

        void IPlayer.resume()
        {
            boolIsPaused = false;
            mplayer.play();
            //throw new NotImplementedException();
        }

        void IPlayer.stop()
        {
            mplayer.stop();
            //throw new NotImplementedException();
        }

        void IPlayer.setVolume(double vol)
        {
            try
            {
            	mplayer.settings.volume = Convert.ToInt32(vol*100);
            }
            catch (System.Exception ex)
            {
            	
            }
            //throw new NotImplementedException();
        }

        double IPlayer.getVolume()
        {
            //throw new NotImplementedException();
            return mplayer.settings.volume*1.0/100;
        }

        void IPlayer.distroy()
        {
            mplayer.stop();
            mplayer.close();
        }


        public event PlayerEventHandler BufferingBegin;

        public event PlayerEventHandler BufferingEnd;

        public event PlayerFailedEventHandler PlayFailed;

        public event PlayerEventHandler PlayFinished;

        public event PlayerTickEventHandler PlayerTicked;

        #endregion

        #region Private Event Handler

        void mplayer_PlayStateChange(int NewState)
        {
            Debug.WriteLine(mplayer.status);
            if (mplayer.currentItem != null)
            {
            	MimiDouban.Test.TestLog.getInstance().info("mplayer_PlayStateChange:" + NewState + ",playstate:" + mplayer.playState.ToString() + ",name:" + mplayer.currentItem.name);
            }
            if ( NewState == 8 )//media ended
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                Debug.WriteLine("state 8");
                if (PlayFinished != null)
                {
                    MimiDouban.Test.TestLog.getInstance().info("mplayer_PlayStateChange playFinished invoke");
                    PlayFinished.Invoke();
                }
            }
            if (NewState == 0) // 0 Undefined
            {
                Debug.WriteLine("state 0");
            }
            if (NewState == 1) // media stoped
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                Debug.WriteLine("state 1");
                //if (PlayFinished != null)
                //{
                //    PlayFinished.Invoke();
                //}
            }
            if (NewState == 6)//6 Buffering The current media item is getting additional data from the server. 
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                bufferTimer = new Timer(new TimerCallback(bufferTimerHandler));
                bufferTimer.Change(10000, Timeout.Infinite);
                Debug.WriteLine("state 6");
                if (BufferingBegin != null)
                {
                    BufferingBegin.Invoke();
                }
            }
            if (NewState == 10)//10 Ready Ready to begin playing.  
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                //mplayer.play();
                bufferTimer = new Timer(new TimerCallback(bufferTimerHandler));
                bufferTimer.Change(15000, Timeout.Infinite);
                Debug.WriteLine("state 10");
            }
            if (NewState == 7)//7 Waiting Connection is established, but the server is not sending data. Waiting for session to begin.  
            {
                Debug.WriteLine("state 7");
                //if (BufferingBegin != null)
                //{
                //    BufferingBegin.Invoke();
                //}
            }
            if (NewState == 9)//9 Transitioning Preparing new media item.
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                bufferTimer = new Timer(new TimerCallback(bufferTimerHandler));
                bufferTimer.Change(10000, Timeout.Infinite);
                Debug.WriteLine("state 9");
                //if (BufferingBegin != null)
                //{
                //    BufferingBegin.Invoke();
                //}
            }
            if (NewState == 2)//2 Paused Playback of the current media item is paused.
            {
                Debug.WriteLine("state 2");
                //if (BufferingBegin != null)
                //{
                //    BufferingBegin.Invoke();
                //}
            }
            if (NewState == 3)//3 Playing The current media item is playing.
            {
                if (bufferTimer != null)
                {
                    bufferTimer.Dispose();
                }
                if (BufferingEnd != null)
                {
                    BufferingEnd.Invoke();
                }
                Debug.WriteLine("state 3");
            }
            //Value State Description 
            //0 Undefined Windows Media Player is in an undefined state. 
            //1 Stopped Playback of the current media item is stopped. 
            //2 Paused Playback of the current media item is paused. When a media item is paused, resuming playback begins from the same location. 
            //3 Playing The current media item is playing. 
            //4 ScanForward The current media item is fast forwarding. 
            //5 ScanReverse The current media item is fast rewinding. 
            //6 Buffering The current media item is getting additional data from the server. 
            //7 Waiting Connection is established, but the server is not sending data. Waiting for session to begin. 
            //8 MediaEnded Media item has completed playback. 
            //9 Transitioning Preparing new media item. 
            //10 Ready Ready to begin playing. 
            //11 Reconnecting Reconnecting to stream. 

        }

        void mplayer_EndOfStream(int Result)
        {
            if ( mplayer.currentItem != null )
            {
            	MimiDouban.Test.TestLog.getInstance().info("mplayer_EndOfStream  ,name: " + mplayer.currentItem.name);
            }
            //throw new NotImplementedException();
        }

        void mplayer_MediaError(object pMediaObject)
        {
            MimiDouban.Test.TestLog.getInstance().info("mplayer_MediaError :" + "code:" + mplayer.errorCode + ",errorContext:" + mplayer.errorContext + ",errorDes:" + mplayer.errorDescription + ",errorCount:" + mplayer.errorCount);
            if (PlayFailed != null)
            {
                PlayFailed.Invoke(new Exception());
                //throw new NotImplementedException();
            }
        }

        void mplayer_Buffering(bool Start)
        {
            if ( mplayer.currentItem != null )
            {
            	MimiDouban.Test.TestLog.getInstance().info("mplayer_Buffering  ,name: " + mplayer.currentItem.name);
            }
            if (BufferingBegin != null)
            {
                BufferingBegin.Invoke();
            }
        }

        private void mplayer_BufferingEnded(object sender, EventArgs e)
        {
            if (BufferingEnd != null)
            {
                BufferingEnd.Invoke();
            }
        }

        private void triggerTickMethod()
        {
            if (PlayerTicked != null && mplayer != null)
            {
                PlayerTicked.Invoke((int)this.mplayer.currentPosition); 
            }        
        }

        private void timerHandlerMethod(object arg)
        {
            this.dispatcher.Invoke(new TickDelegate(triggerTickMethod),null);
        }

        private void bufferTriggerTickMethod()
        {
            if ( mplayer.currentItem != null )
            {
            	MimiDouban.Test.TestLog.getInstance().info("media player ,bufferTriggerTickMethod  ,name: " + mplayer.currentItem.name + ",state:" + mplayer.playState.ToString());
            }
            //如果超过预定缓冲时间，强行下一首
            try
            {
                if (mplayer.playState == WMPLib.WMPPlayState.wmppsBuffering || mplayer.playState == WMPLib.WMPPlayState.wmppsTransitioning || mplayer.playState == WMPLib.WMPPlayState.wmppsReady)
                {
                    if ( mplayer.playState == WMPLib.WMPPlayState.wmppsReady )
                    {
                        mplayer.play();
                    } 
                    else
                    {
                        mplayer.stop();
                        this.PlayFinished.Invoke();
                    }
                    if ( mplayer.currentItem != null )
                    {
                        MimiDouban.Test.TestLog.getInstance().info("media player ,bufferTriggerTickMethod in if ,name: " + mplayer.currentItem.name + ",state:" + mplayer.playState.ToString());
                    }
                }
            }
            catch (System.Exception ex)
            {
                MimiDouban.Test.TestLog.getInstance().error("bufferTriggerTickMethod catch:", ex);

            }
            if ( mplayer.playState == WMPLib.WMPPlayState.wmppsReady )
            {
                MimiDouban.Test.TestLog.getInstance().info("mplayer_MediaError :" + "code:" + mplayer.errorCode + ",errorContext:" + mplayer.errorContext + ",errorDes:" + mplayer.errorDescription + ",errorCount:" + mplayer.errorCount);
            }
        }

        private void bufferTimerHandler(object arg)
        {
            if ( mplayer.currentItem!=null )
            {
            	MimiDouban.Test.TestLog.getInstance().info("media player ,bufferTimerHandler  ,name: " + mplayer.currentItem.name);
            }
            
            this.dispatcher.Invoke(new TickDelegate(bufferTriggerTickMethod),null);
        }

        #endregion    
    }
}
